using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq.Expressions;

namespace Util.DataBase
{
    /// <summary>
    /// 创建人：宙冰
    /// 日  期：2020.04.04
    /// 描  述：数据库操作基本抽象类
    /// </summary>
    public abstract class DbContext<T> : BaseDbContext
        where T : class, new()
    {
        /// <summary>
        /// 指定数据表的下下文
        /// 用来处理T表的常用操作
        /// </summary>
        public SimpleClient<T> db;

        public DbContext()
        {
            db = new SimpleClient<T>(dbContext);
        }

        /// <summary>
        /// 创建查询实体
        /// </summary>
        /// <returns></returns>
        public virtual ISugarQueryable<T> CreateQueryable()
        {
            return dbContext.Queryable<T>();
        }

        /// <summary>
        /// 获得简单数据上下文
        /// </summary>
        /// <returns></returns>
        public SimpleClient<T> GetSimpleClient()
        {
            return db;
        }

        /// <summary>
        /// 获得数据上下文
        /// </summary>
        /// <returns></returns>
        public SqlSugarClient GetClient()
        {
            return dbContext;
        }

        /// <summary>
        /// 根据键值获得数据
        /// </summary>
        /// <param name="id">键值</param>
        /// <returns></returns>
        public virtual T GetById(dynamic id)
        {
            return db.GetById(id);
        }

        /// <summary>
        /// 获得单个实体信息（如果多于一个，会报错）
        /// </summary>
        /// <param name="whereExpression">条件</param>
        /// <returns></returns>
        public virtual T GetSingle(Expression<Func<T, bool>> whereExpression)
        {
            return db.GetSingle(whereExpression);
        }

        /// <summary>
        /// 获得所有数据信息
        /// </summary>
        /// <returns></returns>
        public virtual List<T> GetList()
        {
            return db.GetList();
        }

        /// <summary>
        /// 按指定条件获得数据
        /// </summary>
        /// <param name="whereExpression">条件</param>
        /// <returns></returns>
        public virtual List<T> GetList(Expression<Func<T, bool>> whereExpression)
        {
            return db.GetList(whereExpression);
        }

        /// <summary>
        /// 按指定条件获得分页数据
        /// </summary>
        /// <param name="whereExpression">条件</param>
        /// <param name="pm">分页信息</param>
        /// <returns></returns>
        public virtual List<T> GetPageList(Expression<Func<T, bool>> whereExpression, PageModel pm)
        {
            return db.GetPageList(whereExpression, pm);
        }

        /// <summary>
        /// 按指定条件获得分页数据
        /// </summary>
        /// <param name="whereExpression">条件</param>
        /// <param name="pm">分页信息</param>
        /// <param name="orderByExpression">排序条件</param>
        /// <param name="orderByType">排序方向</param>
        /// <returns></returns>
        public virtual List<T> GetPageList(Expression<Func<T, bool>> whereExpression, PageModel pm, Expression<Func<T, object>> orderByExpression = null, OrderByType orderByType = OrderByType.Asc)
        {
            return db.GetPageList(whereExpression, pm, orderByExpression, orderByType);
        }

        /// <summary>
        /// 按指定条件获得分页数据和总记录数
        /// </summary>
        /// <param name="queryable">查询条件</param>
        /// <param name="pm">分页信息</param>
        /// <returns></returns>
        public virtual Tuple<List<T>, int> GetPageListAndTotal(ISugarQueryable<T> queryable, PageModel pm)
        {
            int total = 0;
            List<T> list = queryable.ToPageList(pm.PageIndex, pm.PageSize, ref total);
            return new Tuple<List<T>, int>(list, total);
        }

        /// <summary>
        /// 获得指定条件的数据数量
        /// </summary>
        /// <param name="whereExpression">条件</param>
        /// <returns></returns>
        public virtual int GetCount(Expression<Func<T, bool>> whereExpression)
        {
            return db.Count(whereExpression);
        }

        /// <summary>
        /// 插入数据
        /// </summary>
        /// <param name="model">实体信息</param>
        /// <returns></returns>
        public virtual bool Insert(T model)
        {
            return db.Insert(model);
        }

        /// <summary>
        /// 插入数据并返回自动生成的键值
        /// </summary>
        /// <param name="model">数据实体</param>
        /// <returns></returns>
        public virtual int InsertReturnIdentity(T model)
        {
            return db.InsertReturnIdentity(model);
        }

        /// <summary>
        /// 指插入数据
        /// </summary>
        /// <param name="models">实体信息集</param>
        /// <returns></returns>
        public virtual bool Insert(List<T> models)
        {
            return db.InsertRange(models);
        }

        /// <summary>
        /// 更新数据
        /// </summary>
        /// <param name="model">实体信息</param>
        /// <returns></returns>
        public virtual bool Update(T model)
        {
            return db.Update(model);
        }

        /// <summary>
        /// 批量更新数据
        /// </summary>
        /// <param name="models">数据</param>
        /// <returns></returns>
        public virtual bool UpdateRange(List<T> models)
        {
            return db.UpdateRange(models);
        }

        /// <summary>
        /// 更新数据
        /// </summary>
        /// <param name="columns">指定要更新的字段</param>
        /// <param name="model">实体信息</param>
        /// <returns></returns>
        public virtual int UpdateIncludeColumns(T model, params string[] columns)
        {
            return db.AsUpdateable(model).UpdateColumns(columns).ExecuteCommand();
        }

        /// <summary>
        /// 更新数据
        /// </summary>
        /// <param name="columns">指定不要更新的字段</param>
        /// <param name="model"></param>
        /// <returns></returns>
        public virtual int UpdateExcludeColumns(T model, params string[] columns)
        {
            return db.AsUpdateable(model).IgnoreColumns(columns).ExecuteCommand();
        }

        /// <summary>
        /// 按键值删除数据
        /// </summary>
        /// <param name="id">键值</param>
        /// <returns></returns>
        public virtual bool Delete(dynamic id)
        {
            return db.DeleteById(id);
        }

        /// <summary>
        /// 按键值删除数据
        /// </summary>
        /// <param name="id">键值</param>
        /// <returns></returns>
        public virtual bool Delete(dynamic[] ids)
        {
            return db.DeleteByIds(ids);
        }

        /// <summary>
        /// 按条件删除数据
        /// </summary>
        /// <param name="whereExpression"></param>
        /// <returns></returns>
        public virtual int Delete(Expression<Func<T, bool>> whereExpression)
        {
            return dbContext.Deleteable<T>(whereExpression).ExecuteCommand();
        }
    }
}
